(function () {
    let PEDDING = 'pedding';
    let RESOLVED = 'resolved';
    let REJECTED = 'rejected';
    function myPromise(excutor) {
        this.data = null;
        this.status = PEDDING;
        this.callBacks = [];

        const resolve = (data) => {
            if (this.status !== PEDDING) {
                return
            }
            this.data = data;
            this.status = RESOLVED;
            if (this.callBacks.length) {
                setTimeout(() => {
                    this.callBacks.forEach(callBackObj => {
                        callBackObj.onResolved(data)
                    })
                })
            }

        }

        const reject = (data) => {
            if (this.status !== PEDDING) {
                return
            }
            this.data = data;
            this.status = REJECTED;
            if (this.callBacks.length) {
                setTimeout(() => {
                    this.callBacks.forEach(callBackObj => {
                        callBackObj.onRejected(data)
                    })
                })
            }
        }

        try {
            excutor(resolve, reject)
        } catch (err) {
            reject(err)
        }

        myPromise.prototype.then = (onResolved, onRejected) => {
            return new myPromise((resolve, reject) => {
                let self = this;
                function handle(callback) {
                    try {
                        const result = callback(self.data);
                        if (result instanceof myPromise) {
                            result.then(
                                (value) => {
                                    resolve(value);
                                },
                                (error) => {
                                    reject(error);
                                }
                            );
                        } else {
                            resolve(result);
                        }
                    } catch (err) {
                        reject(err)
                    }
                }

                if (this.status === PEDDING) {
                    this.callBacks.push({
                        onResolved: () => {
                            handle(onResolved);
                        },
                        onRejected: () => {
                            handle(onRejected);
                        },
                    })
                } else if (this.status === RESOLVED) {
                    setTimeout(() => {
                        handle(onRejected);
                    });
                } else if (this.status === REJECTED) {
                    setTimeout(() => {
                        handle(onRejected);
                    });
                }
            })

        }
        myPromise.prototype.catch = (onRejected) => {
            return this.then(undefined, onRejected);
        }
    }
    window.myPromise = myPromise;
})()

function test() {
    return new myPromise((resolve, reject) => {
        setTimeout(() => {
            reject(21)
        }, 500)
    })

}

test().then(res => {
    console.log('res', res)
}, err => {
    console.log('err', err)
})